package net.stogi.dsper.ui.client.module.dataobject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;

import net.stogi.common.gwt.dispatch.client.core.ActionManager;
import net.stogi.common.gwt.frame.client.core.EventBus;
import net.stogi.common.gwt.frame.client.mvp.AbstractPresenter;
import net.stogi.common.mvp.core.behavior.BehaviorWithValue;
import net.stogi.common.mvp.core.model.KeyValues;
import net.stogi.dsper.api.dto.DataObjectDto;
import net.stogi.dsper.ui.shared.module.dataobject.ListDataObjectsAction;
import net.stogi.dsper.ui.shared.module.dataobject.ListDataObjectsResult;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

class DataObjectListPresenter extends AbstractPresenter {

	private DataObjectListView dataObjectListView;

	private List<DataObjectDto> dataObjectListModel;

	public DataObjectListPresenter(DataObjectListView dataObjectListView, ActionManager actionManager, EventBus eventBus) {
		super(actionManager, eventBus);
		this.dataObjectListView = dataObjectListView;
		initBehavior();
		initHandlers();
	}

	@Override
	protected void initBehavior() {
		dataObjectListView.setRowSelectedBehavior(new BehaviorWithValue<KeyValues<String>>() {

			@Override
			public void behave(KeyValues<String> value) {
				if (value != null) {
					eventBus.fireEvent(new OpenDataObjectPreviewEvent(internalGetDataObjectFromModel(value.getKey())));
				}
			}
		});
	}

	@Override
	protected void initHandlers() {
		eventBus.addHandler(CloseDataObjectListEvent.TYPE, new CloseDataObjectListHandler() {

			@Override
			public void onCloseDataObjectList(CloseDataObjectListEvent event) {
				dataObjectListView.disappear();
			}
		});
		eventBus.addHandler(OpenDataObjectListEvent.TYPE, new OpenDataObjectListHandler() {

			@Override
			public void onOpenDataObjectList(OpenDataObjectListEvent event) {
				dataObjectListView.appear();
				executeListDataObjects();
			}
		});
	}

	private void executeListDataObjects() {
		actionManager.execute(new ListDataObjectsAction(), new AsyncCallback<ListDataObjectsResult>() {

			@Override
			public void onFailure(Throwable caught) {
				internalHandleException(caught);
			}

			@Override
			public void onSuccess(ListDataObjectsResult result) {
				dataObjectListModel = result.getDataObjects();
				internalDisplayDataObjects(dataObjectListModel);
			}
		});
	}

	private void internalDisplayDataObjects(List<DataObjectDto> dataObjectList) {
		List<KeyValues<String>> modelList = new ArrayList<KeyValues<String>>();
		for (DataObjectDto dataObject : dataObjectList) {
			KeyValues<String> model = new KeyValues<String>(dataObject.getDataValues().get("title"));
			model.setValue("dataSourceName", dataObject.getDataSourceName());
			model.setValue("userProfileName", dataObject.getUserProfileName());
			for (Entry<String, String> entry : dataObject.getDataValues().entrySet()) {
				model.setValue(entry.getKey(), entry.getValue());
			}
			modelList.add(model);
		}
		dataObjectListView.displayDataObjects(modelList);
	}

	private void internalHandleException(Throwable caught) {
		// TODO: Add some nice message module in order to show messages from
		// exceptions to user.
		GWT.log("execute*: fail", null);
	}

	private DataObjectDto internalGetDataObjectFromModel(String title) {
		for (DataObjectDto dataObject : dataObjectListModel) {
			String value = dataObject.getDataValues().get("title");
			if (value != null && value.equals(title)) {
				return dataObject;
			}
		}
		return null;
	}
}
